{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "实践建议\n",
    "\n",
    "1. **优先使用 RAII 容器**：如 `std::unique_ptr`, `std::shared_ptr`, `std::vector` 等，避免手动管理内存。\n",
    "2. **自定义 allocator 时保持一致**：在标准容器中使用自定义 allocator，内部会适配 `allocator::allocate` / `deallocate`，无需直接调用 `new/malloc`。\n",
    "3. **性能敏感场景**：根据需求考虑内存池、arena allocator、自定义 `operator new` 或使用 PMR 提供的 `std::pmr::monotonic_buffer_resource`。\n",
    "4. **混合语言互调**：与 C 库接口交互时，可在 C 接口层统一使用 `malloc/free`，在 C++ 层通过封装转换为 RAII 对象，或设计专门的 bridge（桥接）函数。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "基本概念与原理\n",
    "\n",
    "| 方面             | `new` / `delete`                                             | `malloc` / `free`                                            |\n",
    "| ---------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |\n",
    "| 所属范畴         | C++ 语言层面                                                 | C 标准库 `<cstdlib>`                                         |\n",
    "| 返回类型         | 自动推导为指定类型指针，并可抛异常                           | 返回 `void*`，需强制转换                                     |\n",
    "| 对象生命周期     | 调用构造函数 / 析构函数，管理完整对象生命周期                | 只分配 / 释放原始内存，不调用构造 / 析构                     |\n",
    "| 对齐 (alignment) | 按目标类型所需对齐进行                                       | 基于实现的默认对齐，可通过 `std::aligned_alloc` 获取特定对齐 |\n",
    "| 错误处理         | 默认抛出 `std::bad_alloc`；可使用 nothrow 版本返回 `nullptr` | 分配失败返回 `nullptr`                                       |\n",
    "| 自定义行为       | 可自定义全局 / 类成员的 `operator new/delete`                | 可自定义 allocator 或使用替代 API                            |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`new` / `delete`\n",
    "- **数组 delete** 必须使用 `delete[]`，以调用正确数量的析构函数并释放内部记录的元素数量信息。\n",
    "- C++20 引入的 **显式默认初始化 `new T()`** 与值初始化 `new T{}` 的差异依旧存在：\n",
    "  - `new int()` → 值初始化为 0。\n",
    "  - `new int` → 未初始化，内容不确定。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "// 单对象\n",
    "auto p = new Widget(/* 构造参数 */);\n",
    "delete p;\n",
    "\n",
    "// 数组对象\n",
    "auto arr = new Widget[10];\n",
    "delete[] arr;\n",
    "\n",
    "// nothrow 版本\n",
    "auto q = new (std::nothrow) Widget;\n",
    "if (!q) {\n",
    "    // 处理分配失败\n",
    "}\n",
    "\n",
    "// 定位 new（placement new）\n",
    "void* raw = operator new(sizeof(Widget)); // 仅分配内存\n",
    "Widget* obj = new(raw) Widget(/*构造*/);  // 原地构造\n",
    "obj->~Widget();                           // 手动析构\n",
    "operator delete(raw);                     // 释放内存"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "`malloc` / `free`\n",
    "- **不得对非 POD（Plain Old Data）的 C++ 对象使用 `malloc` 构造**，除非显式调用 placement new 构造对象并在释放前手动调用析构函数。\n",
    "- C++20 中仍沿用传统 `malloc/free` 行为，若需对齐分配请使用 `std::aligned_alloc`（其对齐和大小要求严格：大小必须是对齐值的倍数）。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "vscode": {
     "languageId": "cpp"
    }
   },
   "outputs": [],
   "source": [
    "#include <cstdlib>\n",
    "\n",
    "int* p = static_cast<int*>(std::malloc(sizeof(int) * 10));\n",
    "if (!p) {\n",
    "    // 分配失败\n",
    "}\n",
    "\n",
    "// 使用后\n",
    "std::free(p);"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "内存管理流程对比\n",
    "\n",
    "| 步骤            | `new`                   | `delete`               | `malloc`                                 | `free`             |\n",
    "| --------------- | ----------------------- | ---------------------- | ---------------------------------------- | ------------------ |\n",
    "| 1. 获取原始内存 | 调用对应 `operator new` | -                      | 调用运行时分配器（通常是 `malloc` 实现） | -                  |\n",
    "| 2. 构造对象     | 调用构造函数            | -                      | 需显式调用 placement new                 | -                  |\n",
    "| 3. 使用对象     | 正常使用                | 正常使用               | 指针指向原始内存                         | -                  |\n",
    "| 4. 析构对象     | -                       | 调用析构函数           | 需显式调用析构函数                       | -                  |\n",
    "| 5. 释放内存     | -                       | 调用 `operator delete` | -                                        | 调用运行时回收内存 |"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "缺陷与注意事项\n",
    "\n",
    "**`new` / `delete`**\n",
    "\n",
    "1. **抛异常的开销**：默认失败抛出 `std::bad_alloc`，对于不启用异常的系统环境需使用 nothrow 版本并检查返回值。\n",
    "2. **数组分配隐藏信息**：`new[]` 实现通常会在分配块中存储元素数量，导致与 `delete` 之间的配套使用要求严格。\n",
    "3. **重载复杂度**：自定义 `operator new/delete` 可能破坏全局行为，需要小心管理对齐、异常安全。\n",
    "4. **多线程环境下性能**：标准实现的 `operator new/delete` 可能存在锁开销，需视编译器和标准库实现而定，可使用自定义内存资源或 allocator 优化。\n",
    "\n",
    "**`malloc` / `free`**\n",
    "\n",
    "1. **类型安全缺失**：返回 `void*`，需手动转换，易产生错配类型错误。\n",
    "2. **未调用构造 / 析构**：对于非平凡类型必须搭配 placement new 和显式析构，否则出现未构造或资源泄露。\n",
    "3. **对齐限制**：默认对齐可能不足以满足某些类型的要求，需使用 `std::aligned_alloc` 或特定平台扩展（如 POSIX 的 `posix_memalign`）。\n",
    "4. **与 `new` 混用错误**：不得将 `malloc` 分配的内存交给 `delete`，也不得将 `new` 分配的内存交给 `free`，否则引发未定义行为。\n",
    "5. **分配失败需手动检查**：必须显式判断返回指针是否 `nullptr`。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "C++20 新特性相关补充\n",
    "\n",
    "- **`std::allocate_shared` 与多态 allocators**：可结合 C++20 polymorphic(具备多态性的) memory resources（PMR）提供更灵活的内存管理策略，但其底层仍以 `operator new` 或自定义 allocator 为基础。\n",
    "- **constexpr new/delete**：C++20 扩展了 `constexpr` 中对动态内存的支持，允许在某些 constexpr 场景使用 `new/delete`（仍有编译器支持限制）。\n",
    "- **`operator new` 中处理对齐**：C++17 引入 `::operator new(std::size_t, std::align_val_t)` 支持过对齐分配，C++20 延续此特性，需与 `operator delete` 对应版本配套使用。"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "C++17",
   "language": "C++17",
   "name": "xcpp17"
  },
  "language_info": {
   "name": "C++17"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
